# -*- coding: utf-8 -*-
# This code written by ChanGOGOGO
""" """
import logging
from operator import call
import os.path
import time
import requests
import hashlib
import base64
import hmac
from util import (
    post_json,
    random_str,
    random_phone,
    data2beautify,
    encrypy_md5,
    encrypt_aes,
    get_now_time,
    read_yaml,
)


class OpenAPI:

    def __init__(self, env):
        env = env.lower()
        config = read_yaml(f"./config/{env}.yaml")
        ip = config["interface_ip"]  # 接口ip
        port = config["interface_port"]  # 接口端口
        self.app_key = str(config["app_key"])
        self.app_secret = config["app_secret"]
        if not self.app_secret:
            self.url_prefix = f"http://{ip}:{port}/yicall/api/{self.app_key}"
        else:
            self.url_prefix = f"http://{ip}:{port}/yicall/api/token"
        self.headers = self.get_headers()

    def get_sign(self, timestamp):
        data = f"{self.app_key}{timestamp}"
        if not self.app_secret:
            return ""
        try:
            # 进行HMAC-SHA1加密
            hmac_obj = hmac.new(
                self.app_secret.encode("utf-8"), data.encode("utf-8"), hashlib.sha1
            )
            # 加密结果进行Base64编码
            result = base64.b64encode(hmac_obj.digest()).decode("utf-8")
            return result
        except Exception as e:
            logging.error(f"Failed to generate HMAC-SHA1: {e}")
            return ""

    def get_headers(self):
        if self.app_secret:
            timestamp = str(int(time.time()))
            sign = self.get_sign(timestamp)
            headers = {
                "Content-Type": "application/json;charset=UTF-8",
                "appKey": self.app_key,
                "timestamp": timestamp,
                "sign": sign,
            }
        else:
            headers = {"Content-Type": "application/json;charset=UTF-8"}
        logging.info(f"请求头：\n{data2beautify(headers)}")
        return headers

    def create_callout_task(self, template_id: str, out_task_id: str, **kwargs):
        """创建外呼任务"""
        url = f"{self.url_prefix}/createOpenCall"
        """获取非必填参数的值。如果参数值为not_required，则接口请求中不传递该参数"""
        task_name = kwargs.get("task_name", "not_required")  # 任务名称
        voice_template_name = kwargs.get(
            "voice_template_name", "not_required"
        )  # 录音包名称
        callout_number = kwargs.get("callout_number", "not_required")  # 呼出号码
        tel_num_prefix = kwargs.get("tel_num_prefix", "not_required")  # 手机号前缀
        start_call_time = kwargs.get("start_call_time", "not_required")  # 开始呼叫时间
        auto_stop_time = kwargs.get("auto_stop_time", "not_required")  # 自动停止时间
        recall_num = kwargs.get("recall_num", "not_required")  # 重拨次数
        recall_strategy = kwargs.get(
            "recall_strategy", "not_required"
        )  # 重拨策略：1-定时重拨，2-间隔重拨，3-队尾重拨
        recall_time = kwargs.get("recall_time", "not_required")  # 定时重拨时间
        recall_gap = kwargs.get("recall_gap", "not_required")  # 重拨间隔时间
        callout_line_count = kwargs.get(
            "callout_line_count", "not_required"
        )  # 呼出线路数
        tts_engine_id = kwargs.get("tts_engine_id", "not_required")  # TTS引擎ID
        tts_play_mode = kwargs.get(
            "tts_play_mode", "not_required"
        )  # TTS播放模式：playMixTts代表“录音+TTS”，playPureTts代表“纯录音”
        tts_supplier_id = kwargs.get("tts_supplier_id", "not_required")  # TTS供应商ID
        tts_voice_id = kwargs.get("tts_voice_id", "not_required")  # TTS语音ID
        tts_speed = kwargs.get("tts_speed", "not_required")  # TTS语速
        tts_volume = kwargs.get("tts_volume", "not_required")  # TTS音量
        asr_engine_id = kwargs.get("asr_engine_id", "not_required")  # ASR引擎ID
        asr_supplier_id = kwargs.get("asr_supplier_id", "not_required")  # ASR供应商ID
        max_ring_duration = kwargs.get(
            "max_ring_duration", "not_required"
        )  # 最大振铃时长
        task_notice = kwargs.get("task_notice", "not_required")  # 通话记录回调开关
        recall_num_map = kwargs.get(
            "recall_num_map", "not_required"
        )  # 自定义每轮重拨号码
        recall_num_checked = kwargs.get(
            "recall_num_checked", "not_required"
        )  # 自定义重拨号码开关
        error_pause_task_enable = kwargs.get(
            "error_pause_task_enable", "not_required"
        )  # 异常暂停开关
        error_pause_task_error_num = kwargs.get(
            "error_pause_task_error_num", "not_required"
        )  # 异常占比百分之X暂停任务
        connect_rate_alert_settings = kwargs.get(
            "connect_rate_alert_settings", "not_required"
        )  # 接通率告警设置
        connect_rate_alert_enable = kwargs.get(
            "connect_rate_alert_enable", "not_required"
        )  # 接通率告警开关
        alert_ways = kwargs.get(
            "alert_ways", "not_required"
        )  # 接通率告警方式：1-页面，2-企微
        black_group_ids = kwargs.get("black_group_ids", "not_required")  # 黑名单分组ID
        black_group_enable = kwargs.get(
            "black_group_enable", "not_required"
        )  # 黑名单分组开关
        check_duplicate_case_id = kwargs.get(
            "check_duplicate_case_id", "not_required"
        )  # 限制case_id不得重复开关
        tel_valid = kwargs.get("tel_valid", "not_required")  # 号码有效性校验开关
        business_hours_limit = kwargs.get(
            "business_hours_limit", "not_required"
        )  # 营业时间限制开关
        business_hours_settings = kwargs.get(
            "business_hours_settings", "not_required"
        )  # 营业时间设置
        phone_num = kwargs.get("phone_num", 0)  # 手机号码数量
        custom_variable = kwargs.get(
            "custom_variable", "not_required"
        )  # 用户号码自定义变量
        data = {
            "seqNo": random_str(32),
            "data": {"strategy": {"outTaskId": out_task_id, "templateId": template_id}},
        }
        """如果非必填参数值不为not_required，则请求接口时入参中添加该参数"""
        if task_name != "not_required":
            data["data"]["strategy"]["outTaskName"] = task_name
        if voice_template_name != "not_required":
            data["data"]["strategy"]["voiceTemplateName"] = voice_template_name
        if callout_number != "not_required":
            data["data"]["strategy"]["mainCalloutNumber"] = callout_number
        if tel_num_prefix != "not_required":
            data["data"]["strategy"]["telNumPrefix"] = tel_num_prefix
        if start_call_time != "not_required":
            data["data"]["strategy"]["startCallTime"] = start_call_time
        if auto_stop_time != "not_required":
            data["data"]["strategy"]["autoStopTime"] = auto_stop_time
        if recall_num != "not_required":
            data["data"]["strategy"]["recallNum"] = recall_num
        if recall_strategy != "not_required":
            data["data"]["strategy"]["recallStrategy"] = recall_strategy
        if recall_time != "not_required":
            data["data"]["strategy"]["recallTime"] = recall_time
        if recall_gap != "not_required":
            data["data"]["strategy"]["recallGap"] = recall_gap
        if callout_line_count != "not_required":
            data["data"]["strategy"]["calloutLineCount"] = callout_line_count
        if (
            (tts_play_mode != "not_required")
            or (tts_supplier_id != "not_required")
            or (tts_voice_id != "not_required")
        ):
            data["data"]["strategy"]["ttsSupplier"] = {}
        if tts_engine_id != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["engineId"] = tts_engine_id
        if tts_play_mode != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["playMode"] = tts_play_mode
        if tts_supplier_id != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["ttsSupplierId"] = tts_supplier_id
        if tts_voice_id != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["voiceId"] = tts_voice_id
        if tts_speed != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["speed"] = tts_speed
        if tts_volume != "not_required":
            data["data"]["strategy"]["ttsSupplier"]["volume"] = tts_volume
        if (asr_supplier_id != "not_required") or (asr_engine_id != "not_required"):
            data["data"]["strategy"]["asrSupplier"] = {}
        if asr_engine_id != "not_required":
            data["data"]["strategy"]["asrSupplier"]["engineId"] = asr_engine_id
        if asr_supplier_id != "not_required":
            data["data"]["strategy"]["asrSupplier"]["asrSupplierId"] = asr_supplier_id
        if max_ring_duration != "not_required":
            data["data"]["strategy"]["firstRtpTimeout"] = max_ring_duration
        if task_notice != "not_required":
            data["data"]["strategy"]["taskNoticeLimit"] = task_notice
        if recall_num_map != "not_required":
            data["data"]["strategy"]["recallNumerMap"] = recall_num_map
        if recall_num_checked != "not_required":
            data["data"]["strategy"]["recallNumChecked"] = recall_num_checked
        if (
            (error_pause_task_enable != "not_required")
            or (error_pause_task_error_num != "not_required")
            or (connect_rate_alert_enable != "not_required")
            or (connect_rate_alert_settings != "not_required")
            or (alert_ways != "not_required")
            or (black_group_ids != "not_required")
            or (black_group_enable != "not_required")
            or (check_duplicate_case_id != "not_required")
        ):
            data["data"]["strategy"]["alertSetting"] = {}
        if error_pause_task_enable != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "pauseTaskEnable"
            ] = error_pause_task_enable
        if error_pause_task_error_num != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "pauseTaskErrorNum"
            ] = error_pause_task_error_num
        if connect_rate_alert_settings != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "connectRate"
            ] = connect_rate_alert_settings
        if connect_rate_alert_enable != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "connectRateEnable"
            ] = connect_rate_alert_enable
        if alert_ways != "not_required":
            data["data"]["strategy"]["alertSetting"]["alertWays"] = alert_ways
        if black_group_ids != "not_required":
            data["data"]["strategy"]["alertSetting"]["blackGroupIds"] = black_group_ids
        if black_group_enable != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "blackGroupEnable"
            ] = black_group_enable
        if check_duplicate_case_id != "not_required":
            data["data"]["strategy"]["alertSetting"][
                "checkDuplicateCaseId"
            ] = check_duplicate_case_id
        if tel_valid != "not_required":
            data["data"]["strategy"]["telValid"] = tel_valid
        if business_hours_limit != "not_required":
            data["data"]["strategy"]["taskPermitTimeLimit"] = business_hours_limit
        if business_hours_settings != "not_required":
            data["data"]["strategy"]["taskPermitTimeList"] = business_hours_settings
        if phone_num > 0:
            customer_list = list()
            for x in range(phone_num):
                phone = random_phone()
                case_id = random_str(15)
                customer = {
                    "caseId": case_id,
                    "telNum": phone,
                    "calloutScheduleTime": "",
                }
                if custom_variable != "not_required":
                    customer.update(custom_variable)
                customer_list.append(customer)
            customer_info = {"customer": customer_list}
            data["data"].update(**customer_info)
        res = post_json(url, data, log_switch=True, headers=self.headers)
        return res

    def import_phone(
        self,
        inner_task_id,
        customer_infos: list,
        out_task_id=None,
        encryption_type: str = "",
        tel_valid: bool = False,
    ):
        """
        向呼出任务导入手机号
        :param inner_task_id: callplus任务id
        :param customer_infos: 待呼叫客户信息
        :param out_task_id: 外部任务id
        :param encryption_type: 加密方式。空或者不传代表明文，md5、AES
        :param tel_valid: 是否校验手机号的合法性。true是校验，false不校验
        :return:
        """
        url = f"{self.url_prefix}/importUserInfo"
        if (bool(inner_task_id) is False) and (bool(out_task_id) is True):
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "outTaskId": out_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_infos,
                },
            }
        else:
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "innerTaskId": inner_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_infos,
                },
            }
        res = post_json(url, req, log_switch=True, headers=self.headers)
        return res

    def import_random_phone(
        self,
        inner_task_id,
        out_task_id=None,
        phone_num: int = 1,
        encryption_type: str = "",
        aes_key="icekredit2hgzy00",
        tel_valid: bool = False,
        other_customer_info=None,
    ):
        """
        向呼出任务导入手机号
        :param inner_task_id: callplus任务id
        :param out_task_id: 外部任务id
        :param phone_num: 手机号个数
        :param encryption_type: 加密方式。空或者不传代表明文，md5、AES
        :param aes_key: AES加密时，需要传入key
        :param tel_valid: 是否校验手机号的合法性。true是校验，false不校验
        :param other_customer_info: 其他客户信息。来源于：呼出场景变量
        :return:
        """
        url = f"{self.url_prefix}/importUserInfo"
        customer_list = []
        phone_list = []
        start_time = time.time()
        for x in range(phone_num):
            phone = random_phone()
            if encryption_type.lower() == "md5":
                phone = encrypy_md5(phone)
                encryption_type = encryption_type.lower()  # 接口规定md5必须小写
            elif encryption_type.lower() == "aes":
                phone = encrypt_aes(phone, aes_key)
                encryption_type = encryption_type.upper()  # 接口规定AES必须大写
            phone_list.append(phone)
            case_id = random_str(20)
            customer = {
                "caseId": case_id,
                "telNum": phone,
                # 'calloutScheduleTime': ''
            }
            if other_customer_info:
                customer.update(other_customer_info)
            customer_list.append(customer)
        if (bool(inner_task_id) is False) and (bool(out_task_id) is True):
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "outTaskId": out_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        else:
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "innerTaskId": inner_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        end_time = time.time()
        task_time = end_time - start_time
        logging.info(f"生成{phone_num}个手机号耗时{task_time:.2f}秒。")
        now_time = get_now_time()
        # with open("./temp_file/import.csv", "a", encoding="utf-8") as file:
        #     for phone in phone_list:
        #         file.writelines(f"{now_time},{phone}\n")
        res = post_json(url, req, log_switch=True, headers=self.headers)
        return res

    def import_real_time_phone(
        self,
        total_phone: int = 1,
        inner_task_id=None,
        out_task_id=None,
        encryption_type="",
        tel_valid: bool = False,
        other_customer_info=None,
        aes_key="icekredit2hgzy00",
    ):
        url = f"{self.url_prefix}/importAndStartCall"
        customer_list = []
        phone_list = []
        for x in range(total_phone):
            phone = random_phone()
            # phone = "aaaaBBBBCCC"
            if encryption_type.lower() == "md5":
                phone = encrypy_md5(phone)
                encryption_type = encryption_type.lower()  # 接口规定md5必须小写
            elif encryption_type.lower() == "aes":
                phone = encrypt_aes(phone, aes_key)
                encryption_type = encryption_type.upper()  # 接口规定AES必须大写
            phone_list.append(phone)
            case_id = random_str(20)
            customer = {
                "caseId": case_id,
                "telNum": phone,
            }
            if other_customer_info:
                customer.update(other_customer_info)
            customer_list.append(customer)
        if (bool(inner_task_id) is False) and (bool(out_task_id) is True):
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "outTaskId": out_task_id,
                        # "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        else:
            req = {
                "seqNo": random_str(32),
                # "seqNo": "ArGxvunQHjsBvvJuQxByyHtcgGuntLgi",
                "data": {
                    "strategy": {
                        "innerTaskId": inner_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        res = post_json(url, req, log_switch=True, headers=self.headers)
        return res

    def import_increase_phone(
        self,
        inner_task_id,
        out_task_id=None,
        phone_prefix: str = "13",
        total_phone: int = 1,
        encryption_type: str = "",
        aes_key="icekredit2hgzy00",
        tel_valid: bool = False,
        other_customer_info=None,
    ):
        """导入自增+1手机号"""
        number_block_dir = "./temp"
        # 查看目录是否存在，不存在则新建一个
        if os.path.exists(number_block_dir):
            ...
        else:
            os.makedirs(number_block_dir)
        phone_prefix_len = len(phone_prefix)
        supplement_len = 11 - phone_prefix_len  # 需要补充的长度
        start_phone = int(phone_prefix + "0" * supplement_len)
        expect_file_name = f"{number_block_dir}/{phone_prefix}.csv"
        # 从文件中获取当前号段已经使用到哪个尾号了
        if os.path.exists(expect_file_name):
            with open(expect_file_name) as f:
                current_index = int(f.read())
        else:
            current_index = -1
        phones = []
        for x in range(total_phone):
            phone = start_phone + current_index + 1
            phones.append(phone)
            current_index += 1
        with open(expect_file_name, "w", encoding="utf-8") as f:
            f.write(str(current_index))
        customer_list = []
        start_time = time.time()
        for phone in phones:
            if encryption_type.lower() == "md5":
                phone = encrypy_md5(phone)
                encryption_type = encryption_type.lower()  # 接口规定md5必须小写
            elif encryption_type.lower() == "aes":
                phone = encrypt_aes(phone, aes_key)
                encryption_type = encryption_type.upper()  # 接口规定AES必须大写
            case_id = random_str(20)
            customer = {
                "caseId": case_id,
                "telNum": phone,
                # 'calloutScheduleTime': ''
            }
            if other_customer_info:
                customer.update(other_customer_info)
            customer_list.append(customer)
        if (inner_task_id is False) and (out_task_id is True):
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "outTaskId": out_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        else:
            req = {
                "seqNo": random_str(32),
                "data": {
                    "strategy": {
                        "innerTaskId": inner_task_id,
                        "telNumAlg": encryption_type,
                        "telValid": tel_valid,
                    },
                    "customer": customer_list,
                },
            }
        url = f"{self.url_prefix}/importUserInfo"
        res = post_json(url, req, log_switch=True, headers=self.headers)
        return res

    def import_md5_phone(
        self,
        inner_task_id,
        phone_num: int = 1,
        out_task_id=None,
        other_customer_info=None,
    ):
        """
        向呼出任务导入MD5密文手机号
        :param phone_num: 手机号码个数
        :param inner_task_id: callplus任务id
        :param out_task_id: 外部任务id
        :param other_customer_info: 其他客户信息。来源于：呼出场景变量
        :return:
        """
        url = f"{self.url_prefix}/importUserInfo"
        customer_list = []
        for x in range(phone_num):
            case_id = random_str(15)
            phone = encrypy_md5(random_phone(), 32, True)
            customer = {"caseId": case_id, "telNum": phone, "calloutScheduleTime": ""}
            if other_customer_info:
                customer.update(other_customer_info)
            customer_list.append(customer)
        if (inner_task_id is False) and (out_task_id is True):
            req = {
                "seqNo": random_str(),
                "data": {
                    "strategy": {"outTaskId": out_task_id, "telNumAlg": "md5"},
                    "customer": customer_list,
                },
            }
        else:
            req = {
                "seqNo": random_str(),
                "data": {
                    "strategy": {"innerTaskId": inner_task_id, "telNumAlg": "md5"},
                    "customer": customer_list,
                },
            }
        handle_start_time = time.time()
        res = post_json(url, req, log_switch=True, headers=self.headers)
        handle_end_time = time.time()
        handle_take_time = handle_end_time - handle_start_time
        logging.info(f"向接口导入{phone_num}个手机号耗时{handle_take_time:.2f}秒。")
        return res

    def daohong_import_phone(
        self,
        inner_task_id,
        phone_nums: list,
        out_task_id=None,
        other_customer_info=None,
    ):
        """
        向呼出任务导入手机号
        :param inner_task_id: callplus任务id
        :param out_task_id: 外部任务id
        :param phone_nums: 加密手机号列表
        :param other_customer_info: 其他客户信息。来源于：呼出场景变量
        :return:
        """
        url = f"{self.url_prefix}/daohongImportUserInfo"
        customer_list = []
        for phone_num in phone_nums:
            case_id = random_str(15)
            customer = {
                "caseId": case_id,
                "telNum": phone_num,
                "calloutScheduleTime": "",
            }
            if other_customer_info:
                customer.update(other_customer_info)
            customer_list.append(customer)
        if (inner_task_id is False) and (out_task_id is True):
            req = {
                "seqNo": random_str(),
                "data": {
                    "strategy": {"outTaskId": out_task_id},
                    "customer": customer_list,
                },
            }
        else:
            req = {
                "seqNo": random_str(),
                "data": {
                    "strategy": {"innerTaskId": inner_task_id},
                    "customer": customer_list,
                },
            }
        res = post_json(url, req, log_switch=True, headers=self.headers)
        return res

    def update_task(self, inner_task_id=None, out_task_id=None, **kwargs):
        """修改任务信息：可修改外呼线路数，开启/暂停/结束任务"""
        url = f"{self.url_prefix}/updateTaskInfo"
        callout_line_num = kwargs.get("callout_line_num", "not_required")  # 呼出线路数
        task_status = kwargs.get(
            "task_status", "not_required"
        )  # 任务状态. 可选值：startTask-开启任务；pauseTask-暂停任务；finishTask-停止任务。
        if out_task_id:
            data = {"seqNo": random_str(), "data": {"outTaskId": out_task_id}}
        else:
            data = {"seqNo": random_str(), "data": {"innerTaskId": inner_task_id}}
        if callout_line_num != "not_required":
            data["data"]["calloutLineCount"] = callout_line_num
        if task_status != "not_required":
            data["data"]["taskStatus"] = task_status
        res = post_json(url, data, log_switch=True, headers=self.headers)
        return res

    def mark_session_finish(self, case_id, out_task_id=None, inner_task_id=None):
        """
        将呼出任务中某通未拨打的电话置为已完成

        :param case_id: 电话的caseId
        :param out_task_id: 外部任务id
        :param inner_task_id: 内部任务id
        :return: None
        """
        url = f"{self.url_prefix}/markSessionFinish"
        data = {"seqNo": random_str(), "data": {}}
        if out_task_id is not None and inner_task_id is None:
            data["data"]["outTaskId"] = out_task_id
        elif out_task_id is None and inner_task_id is not None:
            data["data"]["innerTaskId"] = inner_task_id
        else:
            data["data"]["outTaskId"] = out_task_id
            data["data"]["innerTaskId"] = inner_task_id
        data["data"]["caseId"] = case_id
        res = post_json(url, data, log_switch=True, headers=self.headers)
        return res

    def pull_call_task(
        self,
        task_type="all",
        bot_template_id=None,
        task_status=None,
        begin_time=None,
        end_time=None,
        page_num=1,
        page_size=1000,
        log_switch=True,
    ):
        """
        拉取符合筛选条件的呼出任务信息
        :param task_type: 任务类型，不传默认为all。openCall-公共服务创建任务；innerCall-话务平台页面创建任务；all-所有创建的任务。
        :param bot_template_id: 筛选的任务所属具体场景组合。
        :param task_status: 任务状态，不传默认为all。unstarted-未开始；progress-进行中；pause-已暂停；finish-已完成。
        :param begin_time: 任务创建的开始时间，格式 yyyy-MM-dd HH:mm:ss，不传默认全部。
        :param end_time: 任务创建的结束时间，格式 yyyy-MM-dd HH:mm:ss，不传默认全部。
        :param page_num: 第几页数据，默认是1。
        :param page_size: 每页返回的数据量，最大不超过1000，默认是1000。
        :param log_switch:
        :return:
        """
        url = f"{self.url_prefix}/pullCallTask"
        data = {
            "seqNo": random_str(),
            "data": {
                "taskType": task_type,
                "botTemplateId": bot_template_id,
                "taskStatus": task_status,
                "beginTime": begin_time,
                "endTime": end_time,
                "pageNum": page_num,
                "pageSize": page_size,
            },
        }
        res = post_json(url, data, log_switch=log_switch, headers=self.headers)
        return res

    def pull_call_session(
        self,
        phone=None,
        start_time=None,
        end_time=None,
        bot_template_id=None,
        call_id=None,
        page_num=1,
        page_size=1000,
    ):
        """
        获取符合筛选条件的通话信息
        :param phone: 客户手机号
        :param start_time: 外呼开始时间，格式YYYY-mm-dd HH:MM:SS，不传默认全部
        :param end_time: 外呼结束时间，格式YYYY-mm-dd HH:MM:SS，不传默认全部
        :param bot_template_id: 会话所属具体场景组合id
        :param page_num: 第几页数据
        :param page_size: 单页数据量，最大不超过1000
        :return:
        """
        url = f"{self.url_prefix}/pullCallSession"
        data = {
            "seqNo": random_str(),
            "data": {
                "botTemplateId": bot_template_id,
                "telNum": phone,
                "callId": call_id,
                "beginTime": start_time,
                "endTime": end_time,
                "pageNum": page_num,
                "pageSize": page_size,
            },
        }
        res = post_json(url, data, log_switch=True, headers=self.headers)
        return res

    def pull_open_call_session(self, out_task_id: str, case_ids: list):
        """"""
        url = f"{self.url_prefix}/pullOpenCallSession"
        data = {
            "seqNo": random_str(),
            "data": {"outTaskId": out_task_id, "caseIds": case_ids},
        }
        res = post_json(url, data, log_switch=True, headers=self.headers)
        return res

    def get_template_list(self):
        """获取业务下场景列表"""
        url = f"{self.url_prefix}/getTemplateList"
        logging.info(f"向{url}接口发送get请求。")
        res = requests.get(url, headers=self.headers).json()
        logging.info(f"从{url}接口得到响应：\n{data2beautify(res)}")
        return res

    def get_scene(self, scene_id: int):
        """获取单个场景信息"""
        url = f"{self.url_prefix}/getScene/{scene_id}"
        logging.info(f"向{url}接口发送get请求。")
        res = requests.get(url, headers=self.headers).json()
        logging.info(f"从{url}接口得到响应：\n{data2beautify(res)}")
        return res

    def import_customer_balcklist(
        self,
        phone_infos: list[tuple],
        group_id: int,
        group_name: str,
        need_aes=0,
        aes_key="",
    ):
        """导入客户黑名单"""
        url = f"{self.url_prefix}/importBlackCustomers"
        black_info = list()
        for phone_info in phone_infos:
            phone, valid_date = phone_info
            if need_aes:
                phone = encrypt_aes(phone, aes_key)
            black_info.append({"phone": phone, "validityDate": valid_date})
        data = {
            "seqNo": random_str(32),
            "data": {
                "groupId": group_id,
                "groupName": group_name,
                "encryptionPhone": need_aes,
                "blackInfo": black_info,
            },
        }
        res = post_json(url, data, headers=self.headers)
        return res

    def query_customer_blacklist_group(self, group_name_keyword=None):
        """查询客户黑名单分组"""
        url = f"{self.url_prefix}/listBlackCustomerGroup"
        data = {"groupNameLike": group_name_keyword}
        res = post_json(url, data, headers=self.headers)
        return res
